package com.viking.car;

import java.io.FileOutputStream;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;

public class Server2 extends Thread{
    private int port = 7981;
    public Server2(int port){
        this.port = port;
    }
    public void run(){
        startServer();
    }

    ServerSocketChannel ssc;
    public void startServer() {
        try {
            Selector selector = Selector.open();
            ServerSocketChannel ssc = ServerSocketChannel.open();
            ssc.configureBlocking(false);
            ServerSocket ss = ssc.socket();
            InetSocketAddress address = new InetSocketAddress(port);
            ss.bind(address);
            ssc.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("端口注册完毕!");
            while (true) {
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iter = selectionKeys.iterator();
                ByteBuffer echoBuffer = ByteBuffer.allocate(148);
                SocketChannel sc;
                while (iter.hasNext()) {
                    SelectionKey key = iter.next();
                    if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
                        ServerSocketChannel subssc = (ServerSocketChannel) key.channel();
                        sc = subssc.accept();
                        sc.configureBlocking(false);
                        sc.register(selector, SelectionKey.OP_READ);
                        iter.remove();
                        System.out.println("有新连接:" + sc);
                    } else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
                        sc = (SocketChannel) key.channel();
                        while (true) {
                            echoBuffer.clear();
                            int a;
                            try {
                                a = sc.read(echoBuffer);
                            } catch (Exception e) {
                                e.printStackTrace();
                                break;
                            }
                            if (a == -1) break;
                            int commandId = 0;
                            int sequenceId = 0;
                            if (a > 0) {
                                byte[] b = echoBuffer.array();
                                /* */
                                FileOutputStream fos = new FileOutputStream("d:\\req1.txt");
                                fos.write(b,0,b.length);//写到文件中，作为对比
                                fos.flush();
                                fos.close(); //
                                Message req = MessageUtils.bytesToMessage(b,false);
                                System.out.println("接收数据: " + req);
                                echoBuffer.flip();
                                commandId = req.getMessageHeader().getCommand_id();
                                sequenceId = req.getMessageHeader().getSequence_id();
                                int respCommandId = Constants.COMMANDID_MAP.get(commandId);
                                String code = checkMessage(req, respCommandId);
                                Message resp = MessageUtils.generateMessage(code, respCommandId,sequenceId,true);
                                sc.write(ByteBuffer.wrap(MessageUtils.messageToBytes(resp)));
                                System.out.println("返回数据: " + resp);
                            }
                        }
                        sc.close();
                        System.out.println("连接结束");
                        System.out.println("=============================");
                        iter.remove();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 根据请求消息进行具体的操作，并将处理结果响应码返回
     * @param req
     * @param respCommandId
     * @return
     */
    //todo 验证客户端请求消息的合法性
    private String checkMessage(Message req, int respCommandId) {
        try {
            //根据要响应的commandId得到响应码
            Map<Integer,String> map = Constants.RESP_CODE_MAP.get(respCommandId);
            if (req == null){ //解析失败,消息错误
                return map.get(Constants.MESSAGE_SRUCT_ERROR);
            }
            //todo 其他错误：token错误，重复动作错误
            Token token = Token.parseToken(req.getMessageBody().getBody());
            System.out.println("得到的客户端token="+token.toFormatString());
            token.printReserved();
            //todo 校验通过后具体操作：取车，开门，锁门，还车

        }catch (IllegalArgumentException e){
            e.printStackTrace();
            return "10101";
        }
        //操作成功，返回成功的响应码
        return "0";
    }
} 